﻿using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

namespace Nirvana
{
    /// <summary>
    /// 任务管理器：控制下载任务执行，避免大量任务拥挤
    /// </summary>
    public class TaskManager
    {
        //最大任务数，超出则任务等待
        private int maxTaskCount = 4;
        public int MaxTaskCount {
            get { return maxTaskCount; }
            set { maxTaskCount = value; }
        }
        //等待执行的任务列表
        private LinkedList<AssetBundleLoadTask> waitTaskList = new LinkedList<AssetBundleLoadTask>();
        //需要执行的任务列表
        private LinkedList<AssetBundleLoadTask> excuteTaskList = new LinkedList<AssetBundleLoadTask>();
        private Action<string> startEvent,finishEvent;
        


        [MethodImpl(MethodImplOptions.Synchronized)]
        public void AddStartEvent(Action<string> action)
        {
            this.startEvent = (Action<string>)Delegate.Combine(startEvent, action);
        }

        [MethodImpl(MethodImplOptions.Synchronized)]
        public void RemoveStartEvent(Action<string> action)
        {
            this.startEvent = (Action<string>)Delegate.Remove(startEvent, action);
        }

        [MethodImpl(MethodImplOptions.Synchronized)]
        internal void AddFinishEvent(Action<string> action)
        {
            this.finishEvent = (Action<string>)Delegate.Combine(this.finishEvent, action);
        }

        [MethodImpl(MethodImplOptions.Synchronized)]
        internal void RemoveFinishEvent(Action<string> action)
        {
            this.finishEvent = (Action<string>)Delegate.Remove(this.finishEvent, action);
        }
        /// <summary>
        /// 任务控制器空闲时，则立即执行
        /// </summary>
        public void AddTask(AssetBundleLoadTask abTask ,bool isFirst = false)
        {
            if (this.excuteTaskList.Count < this.maxTaskCount)
                ExcuteTask(abTask);
            else if (isFirst) //任务数量过多，当前任务等待执行
                this.waitTaskList.AddFirst(abTask);
            else
                this.waitTaskList.AddLast(abTask);
        }

        private void ExcuteTask(AssetBundleLoadTask abTask)
        {
            abTask.StartLoadTask();
            this.excuteTaskList.AddLast(abTask);
            if (this.startEvent != null) this.startEvent(abTask.DownloadUrl);
        }

        /// <summary>
        /// 刷新任务列表
        /// </summary>
        public void ReFreshTask(AssetBundleLoadTask abTask,bool isExcute = false)
        {
            this.excuteTaskList.Remove(abTask);
            if (finishEvent != null)
                this.finishEvent(abTask.DownloadUrl);
            if (isExcute)
                this.ExcuteTask(abTask);
            else
            {
                //当任务数量足够时，检测等待任务是否需要执行
                while(this.excuteTaskList.Count < this.maxTaskCount && this.waitTaskList.Count > 0)
                {
                    var first = this.waitTaskList.First;
                    this.waitTaskList.RemoveFirst();
                    this.ExcuteTask(first.Value);
                }
            }
        }
    }
}

